local Industry = require "industry._base"
local UINodes = require "Data.UINodes"
local _store = {}

local pork_dumplings <const> = 1073938534   --肉粽
local candy_dumplings <const> = 1073954844  --甜粽
local jujube_dumplings <const> = 1073959022 --甜枣粽
local rice_dumplings <const> = 1073950780   --白粽
local yopork_dumplings <const> = 1073946717 --蛋黄肉粽
local yolk_dumplings <const> = 1073942600   --蛋黄粽

---闭区间
---@class closeMinMax
---@field min integer 最小区间
---@field max integer 最大区间

---@class DemandConfig
---@field key EquipmentKey 需求产品编号
---@field base_price integer 基础价格
---@field price_float integer[] 价格浮动
---@field survival_time closeMinMax 订单存活时间
---@field wait_time closeMinMax 客户耐心时间
---@field image integer 图像ID

---@type table<string, DemandConfig>
local DemandS = {
    ["肉粽"] = {
        image = 1,
        key = pork_dumplings,
        base_price = 18,
        price_float = { -2, 10 },
        survival_time = {
            min = 15,
            max = 30
        },
        wait_time = {
            min = 75,
            max = 120
        }
    },
    ["甜粽"] = {
        image = 1,
        key = candy_dumplings,
        base_price = 15,
        price_float = { -2, 10 },
        survival_time = {
            min = 15,
            max = 30
        },
        wait_time = {
            min = 60,
            max = 90
        }
    },
    ["甜枣粽"] = {
        image = 1,
        key = jujube_dumplings,
        base_price = 20,
        price_float = { -2, 10 },
        survival_time = {
            min = 15,
            max = 30
        },
        wait_time = {
            min = 60,
            max = 90
        }
    },
    ["白粽"] = {
        image = 1,
        key = rice_dumplings,
        base_price = 12,
        price_float = { -2, 5 },
        survival_time = {
            min = 15,
            max = 30
        },
        wait_time = {
            min = 45,
            max = 60
        }
    },
    ["蛋黄粽"] = {
        image = 1,
        key = yolk_dumplings,
        base_price = 18,
        price_float = { -2, 10 },
        survival_time = {
            min = 15,
            max = 30
        },
        wait_time = {
            min = 75,
            max = 120
        }
    },
    ["蛋黄肉粽"] = {
        image = 1,
        key = yopork_dumplings,
        base_price = 22,
        price_float = { -2, 10 },
        survival_time = {
            min = 15,
            max = 30
        },
        wait_time = {
            min = 90,
            max = 135
        }
    },
}

---@class storeMeta
---@field level integer 等级
---@field credit integer 信誉分
---@field assets integer 门店资产
---@field bonus integer[] 门店增益状态

---@class Order
---@field demand EquipmentKey 需求产品
---@field price integer 商品价格
---@field fee integer 小费
---@field survial_time integer 订单存活时间
---@field wait_time integer 客户耐心时间
---@field accepted boolean 是否已接单
---@field config_name string 配置名称

---@class Store: Industry
---@field credit integer 信誉分
---@field assets integer 资产
---@field bonus integer[] 增益状态
---@field status boolean 门店状态
---@field display_info table<string, Unit> 信息展示板
---@field bonusVariation integer 增益触发器
---@field orderVariation integer 订单触发器
---@field levelup_unit Unit 升级单元
---@field extra_income integer 订单额外收入
---@field wait_alpha Fixed 等待系数
---@field pending_orders Order[] 未接单订单
---@field accepted_orders Order[] 已接单订单
---@field completed_orders integer 已完成订单计数
---@field current_page integer 当前页数
---@field total_pages integer 总页数
---@field ui_handlers integer[] UI杆柄
---@field ui_open boolean 是否打开
---@field metadata storeMeta 元数据
_store.Store = {}
_store.Store.__index = _store.Store
setmetatable(_store.Store, { __index = Industry })

---构造门店实例
---@param _role Role 门店管理员
---@return Store
function _store.Store:new(_role)
    local parent = Industry:new(_role)
    local instance = setmetatable(parent, self) --[[@as Store]]
    instance.credit = 100
    instance.assets = 0
    instance.bonus = {}
    instance.display_info = {}
    instance.extra_income = 0
    instance.pending_orders = {}
    instance.accepted_orders = {}
    instance.completed_orders = 0
    instance.max_order_count = 2
    instance.status = false
    instance.bonusVariation = -1
    instance.orderVariation = -1
    instance.wait_alpha = 1.0
    instance.ui_open = false
    instance.current_page = 1
    instance.total_pages = 0
    instance.ui_handlers = {}
    instance:bind(_role.get_kv_by_type(Enums.ValueType.Int, "编号"))
    return instance
end

---产业场景绑定
---@param order integer
function _store.Store:bind(order)
    local store_display_name = "门店信息" .. tostring(order)
    local store_display = GameAPI.get_unit(GameAPI.get_unit_id_by_name(store_display_name))
    self.display_info.root = store_display
    self.display_info.name = store_display.get_child_by_name("名称")
    self.display_info.level = store_display.get_child_by_name("等级")
    self.display_info.status = store_display.get_child_by_name("营业状态")

    local store_levelup_name = "门店升级" .. tostring(order)
    local store_levelup = GameAPI.get_unit(GameAPI.get_unit_id_by_name(store_levelup_name))
    store_levelup.set_kv_by_type(Enums.ValueType.Role, "主人", self.owner)
    self.levelup_unit = store_levelup
end

---开始执行
function _store.Store:start()
    self:update_info()
    self:start_bonus()
    self:start_order_timer()
end

---停止执行
function _store.Store:stop()
    self:stop_bonus()
    self:stop_order_timer()
    self:save_data()
    self.display_info.name.set_billboard_content("空铺")
    self.display_info.level.set_billboard_content(" ")
    self.display_info.status.set_billboard_content(" ")
end

---更新信息展示
function _store.Store:update_info()
    self.display_info.name.set_billboard_content(("%s的粽子铺"):format(self.owner.get_name()))
    self.display_info.level.set_billboard_content(("Lvl.%d"):format(self.level))
    self.display_info.status.set_billboard_content(("%s"):format(self.status and "营业中" or "打烊了"))
end

---切换营业状态
function _store.Store:toggle_status()
    self.status = not self.status
    self:update_info()
end

---获得收益
---@param profit integer
function _store.Store:get_profit(profit)
    -- 计算增益倍数
    local final_profit_bonus = 1
    for i = 1, #self.bonus, 2 do
        final_profit_bonus = final_profit_bonus * self.bonus[i]
    end

    -- 信誉分150以上双倍收益
    if self.credit >= 150 then
        final_profit_bonus = final_profit_bonus * 2
    end

    self:improve_assets(profit * final_profit_bonus)
end

---叠加收益增幅
---@param scale integer 增幅
---@param duration integer 持续时间
function _store.Store:add_bonus(scale, duration)
    table.insert(self.bonus, scale)
    table.insert(self.bonus, duration)
    if self.bonusVariation == -1 then
        self:start_bonus()
    end
end

---增幅器启动
function _store.Store:start_bonus()
    self.bonusVariation = LuaAPI.global_register_trigger_event({ EVENT.REPEAT_TIMEOUT, 1 }, function()
        local bonus = self.bonus
        for index = 2, #bonus, 2 do
            bonus[index] = bonus[index] - 1
        end
        local i = 1
        while i <= #bonus do
            if i % 2 == 1 and i + 1 <= #bonus and bonus[i + 1] == 0 then
                table.remove(bonus, i)
                table.remove(bonus, i)
            else
                i = i + 1
            end
        end
        if #bonus == 0 then
            self:stop_bonus()
        end
    end)
end

---增幅器关闭
function _store.Store:stop_bonus()
    if self.bonusVariation ~= -1 then
        LuaAPI.global_unregister_trigger_event(self.bonusVariation)
        self.bonusVariation = -1
    end
end

--- 打开门店订单界面
---@param user Role
function _store.Store:open_gui(user)
    if self.ui_open then
        return
    end

    self.ui_open = true
    self.user = user
    local canvas = UINodes["门店订单"]
    user.set_node_visible(canvas, true)

    -- 注册UI事件
    self:register_ui_events()

    -- 更新订单显示
    self:update_order_display()
end

--- 关闭门店订单界面
function _store.Store:close_gui()
    if not self.ui_open then
        return
    end

    self.ui_open = false
    local canvas = UINodes["门店订单"]
    self.owner.set_node_visible(canvas, false)
    self.user = nil

    -- 清理事件处理器
    self:cleanup_ui_events()
end

--- 注册UI事件
function _store.Store:register_ui_events()
    -- 注册上一页/下一页事件
    table.insert(self.ui_handlers, LuaAPI.global_register_trigger_event(
        { EVENT.CUSTOM_EVENT, "订单上一页" },
        function(_, __, roleInfo)
            if roleInfo.role.get_roleid() == self.owner.get_roleid() then
                self:prev_page()
            end
        end
    ))

    table.insert(self.ui_handlers, LuaAPI.global_register_trigger_event(
        { EVENT.CUSTOM_EVENT, "订单下一页" },
        function(_, __, roleInfo)
            if roleInfo.role.get_roleid() == self.owner.get_roleid() then
                self:next_page()
            end
        end
    ))

    -- 注册接受/拒绝按钮事件
    for i = 1, 9 do
        table.insert(self.ui_handlers, LuaAPI.global_register_trigger_event(
            { EVENT.CUSTOM_EVENT, "接受订单" .. tostring(i) },
            function(_, __, roleInfo)
                if roleInfo.role.get_roleid() == self.owner.get_roleid() then
                    self:accept_ui_order(i)
                end
            end
        ))

        table.insert(self.ui_handlers, LuaAPI.global_register_trigger_event(
            { EVENT.CUSTOM_EVENT, "拒绝订单" .. tostring(i) },
            function(_, __, roleInfo)
                if roleInfo.role.get_roleid() == self.owner.get_roleid() then
                    self:reject_ui_order(i)
                end
            end
        ))
    end
end

--- 清理UI事件
function _store.Store:cleanup_ui_events()
    for _, handler in ipairs(self.ui_handlers) do
        LuaAPI.global_unregister_trigger_event(handler)
    end
    self.ui_handlers = {}
end

--- 更新订单显示
function _store.Store:update_order_display()
    if not self.ui_open then
        return
    end

    -- 获取当前页订单
    local all_orders = {}
    for _, order in ipairs(self.accepted_orders) do
        table.insert(all_orders, { order = order, accepted = true })
    end
    for _, order in ipairs(self.pending_orders) do
        table.insert(all_orders, { order = order, accepted = false })
    end

    -- 计算分页信息
    self.total_pages = math.max(1, math.ceil(#all_orders / 9))
    self.current_page = math.min(self.current_page, self.total_pages)

    -- 更新分页显示
    self.user.set_label_text(UINodes["当前页数"],
        ("%d / %d"):format(self.current_page, self.total_pages))

    -- 隐藏所有订单条目
    for i = 1, 9 do
        self.user.set_node_visible(UINodes["订单条目" .. tostring(i)], false)
    end

    -- 显示当前页订单
    local start_index = (self.current_page - 1) * 9 + 1
    for i = 1, 9 do
        local index = start_index + i - 1
        if index <= #all_orders then
            local order_data = all_orders[index]
            local order = order_data.order

            -- 显示订单条目
            self.user.set_node_visible(UINodes["订单条目" .. tostring(i)], true)

            -- 设置订单名称（已接受的订单特殊标记）
            local name = order_data.accepted and ("[已接受] " .. order.config_name) or order.config_name
            self.user.set_label_text(UINodes["粽子名称" .. tostring(i)], name)

            -- 设置订单收益
            local profit = order.price + order.fee + self.extra_income
            self.user.set_label_text(UINodes["订单收益" .. tostring(i)], ("%d金币"):format(profit))

            -- 设置剩余时间
            local time_text = order_data.accepted and ("耐心: %d秒"):format(order.wait_time)
                or ("存活: %d秒"):format(order.survial_time)
            self.user.set_label_text(UINodes["剩余时间" .. tostring(i)], time_text)

            -- 设置粽子图片
            local config = DemandS[order.config_name]
            if config and config.image then
                LuaAPI.global_send_event({ EVENT.CUSTOM_EVENT, "更改UI图片" }, {
                    ["编号"] = i - 1,
                    ["关联者"] = self.user,
                    ["图片"] = config.image
                })
            end

            -- 控制按钮显示（已接受的订单不显示按钮）
            self.user.set_node_visible(UINodes["接受按钮" .. tostring(i)], not order_data.accepted)
            self.user.set_node_visible(UINodes["拒绝按钮" .. tostring(i)], not order_data.accepted)
        else
            break
        end
    end
end

--- 上一页
function _store.Store:prev_page()
    if self.current_page > 1 then
        self.current_page = self.current_page - 1
        self:update_order_display()
    end
end

--- 下一页
function _store.Store:next_page()
    if self.current_page < self.total_pages then
        self.current_page = self.current_page + 1
        self:update_order_display()
    end
end

--- 接受UI上的订单
---@param ui_index integer UI上的订单索引（1-9）
function _store.Store:accept_ui_order(ui_index)
    if not self.ui_open then
        return
    end

    -- 计算实际订单索引
    local actual_index = (self.current_page - 1) * 9 + ui_index

    -- 获取所有订单（先已接受，后待接受）
    local all_orders = {}
    for _, order in ipairs(self.accepted_orders) do
        table.insert(all_orders, order)
    end
    for _, order in ipairs(self.pending_orders) do
        table.insert(all_orders, order)
    end

    -- 检查索引有效性
    if actual_index < 1 or actual_index > #all_orders then
        return
    end

    local order = all_orders[actual_index]

    -- 只接受待接受的订单
    for i, pending_order in ipairs(self.pending_orders) do
        if pending_order == order then
            self:accept_order(i)
            break
        end
    end

    -- 更新显示
    self:update_order_display()
end

--- 拒绝UI上的订单
---@param ui_index integer UI上的订单索引（1-9）
function _store.Store:reject_ui_order(ui_index)
    if not self.ui_open then
        return
    end

    -- 计算实际订单索引
    local actual_index = (self.current_page - 1) * 9 + ui_index

    -- 获取所有订单（先已接受，后待接受）
    local all_orders = {}
    for _, order in ipairs(self.accepted_orders) do
        table.insert(all_orders, order)
    end
    for _, order in ipairs(self.pending_orders) do
        table.insert(all_orders, order)
    end

    -- 检查索引有效性
    if actual_index < 1 or actual_index > #all_orders then
        return
    end

    local order = all_orders[actual_index]

    -- 只拒绝待接受的订单
    for i, pending_order in ipairs(self.pending_orders) do
        if pending_order == order then
            table.remove(self.pending_orders, i)
            break
        end
    end

    -- 更新显示
    self:update_order_display()
end

---启动订单定时器
function _store.Store:start_order_timer()
    self.orderVariation = LuaAPI.global_register_trigger_event({ EVENT.REPEAT_TIMEOUT, 1 }, function()
        -- 更新未接单订单
        for i = #self.pending_orders, 1, -1 do
            local order = self.pending_orders[i]
            order.survial_time = order.survial_time - 1
            if order.survial_time <= 0 then
                table.remove(self.pending_orders, i)
            end
        end

        -- 更新已接单订单
        for i = #self.accepted_orders, 1, -1 do
            local order = self.accepted_orders[i]
            order.wait_time = order.wait_time - 1
            if order.wait_time <= 0 then
                table.remove(self.accepted_orders, i)
                self.credit = math.max(self.credit - 1, 0) -- 扣除信誉分
            end
        end

        -- 自动生成新订单
        if self.status and #self.pending_orders + #self.accepted_orders < self.max_order_count then
            -- 信誉分低于80时生成概率减半
            if self.credit > 80 or math.random() > 0.5 then
                self:generate_order()
            end
        end
        self:update_order_display()
    end)
end

---停止订单定时器
function _store.Store:stop_order_timer()
    if self.orderVariation ~= -1 then
        LuaAPI.global_unregister_trigger_event(self.orderVariation)
        self.orderVariation = -1
    end
end

---生成新订单
function _store.Store:generate_order()
    if #self.pending_orders >= self.max_order_count then
        return
    end

    -- 随机选择一种粽子需求
    local demand_names = {}
    for name, _ in pairs(DemandS) do
        table.insert(demand_names, name)
    end
    local config_name = demand_names[math.random(1, #demand_names)]
    local config = DemandS[config_name]

    -- 创建订单
    local order = {}
    order.config_name = config_name
    order.demand = config.key
    order.price = config.base_price + GameAPI.random_int(config.price_float[1], config.price_float[2])

    -- 小费计算（信誉分影响）
    local max_fee = order.price / (self.credit >= 120 and 2 or 4)
    order.fee = GameAPI.random_int(1, max_fee)

    -- 应用配置中的时间范围
    order.survial_time = GameAPI.random_int(config.survival_time.min, config.survival_time.max)

    -- 应用等待系数
    local raw_wait = GameAPI.random_int(config.wait_time.min, config.wait_time.max)
    order.wait_time = math.floor(raw_wait * math.tofixed(self.wait_alpha) + 0.5)

    order.accepted = false

    table.insert(self.pending_orders, order)
    self:update_order_display()
end

---接受订单
---@param index integer 订单索引
function _store.Store:accept_order(index)
    if index < 1 or index > #self.pending_orders then
        return
    end

    local order = table.remove(self.pending_orders, index)
    order.accepted = true
    table.insert(self.accepted_orders, order)
    self:update_order_display()
end

---完成订单
---@param index integer 订单索引
function _store.Store:complete_order(index)
    if index < 1 or index > #self.accepted_orders then
        return false
    end

    local order = table.remove(self.accepted_orders, index)
    local total_profit = order.price + order.fee + self.extra_income
    self:get_profit(total_profit)

    -- 订单完成计数
    self.completed_orders = self.completed_orders + 1
    if self.completed_orders >= 5 then
        self.completed_orders = 0
        self.credit = math.min(self.credit + 1, 200) -- 信誉分上限200
    end
    self:update_order_display()

    return true
end

---设置元数据
---@param metadata storeMeta
function _store.Store:set_metadata(metadata)
    Industry.set_metadata(self, metadata)
    self.level = metadata.level
    self.bonus = metadata.bonus
    self.assets = metadata.assets
    self.credit = metadata.credit
    self:set_level(self.level) -- 应用等级属性
end

---保存数据
function _store.Store:save_data()
    self.metadata.level = self.level
    self.metadata.bonus = self.bonus
    self.metadata.assets = self.assets
    self.metadata.credit = self.credit
end

---获取信息
function _store.Store:get_info()
    local assets = self.assets
    local levelup_money = self:get_levelup_money()
    if self.level + 1 <= 30 then
        return ([==[
%s
%s]==]):format(
            assets >= levelup_money and ("可升级(花费 #cffff00%d #cffffff金币)"):format(levelup_money) or
            ("还差 #cffff00%d #cffffff金币升级"):format(levelup_money - assets),
            "本次升级：" .. self:get_levelup_tip()
        )
    else
        return ([==[
%s
%s]==]):format(
            ("当前等级: #cffff00%d#cffffff"):format(self.level),
            "此后升级不再提升，可无限升级。"
        )
    end
end

---获取升级所需金币
function _store.Store:get_levelup_money()
    return 500 * self.level
end

---升级提示
function _store.Store:get_levelup_tip()
    local current_level = self.level
    local next_level = current_level + 1
    local tip = ""

    -- 额外收入变化
    local current_income = current_level <= 30 and current_level or 30
    local next_income = next_level <= 30 and next_level or 30
    if current_income ~= next_income then
        tip = tip .. ("额外收入 #c00ff00%d → %d#cffffff"):format(current_income, next_income)
    end

    -- 最大订单量变化
    if next_level % 3 == 0 and next_level <= 30 then
        local current_max = 2 + math.floor((current_level - 1) / 3)
        local next_max = 2 + math.floor(next_level / 3)
        if tip ~= "" then tip = tip .. "，" end
        tip = tip .. ("最大单量 #c00ff00%d → %d#cffffff"):format(current_max, next_max)
    end

    -- 等待时间系数变化
    if next_level % 2 == 0 and next_level <= 30 then
        local current_alpha = 1.0 + math.tofixed(current_level) / 15
        local next_alpha = 1.0 + math.tofixed(next_level) / 15
        if tip ~= "" then tip = tip .. "，" end
        tip = tip .. ("耐心系数 #c00ff00%.2f → %.2f#cffffff"):format(math.tofixed(current_alpha), math.tofixed(next_alpha))
    end

    return tip ~= "" and tip or "无属性提升"
end

---设置等级
---@param level integer 等级
function _store.Store:set_level(level)
    self.level = level

    -- 30级前属性变化
    if self.level <= 30 then
        self.extra_income = self.level
    end

    -- 每3级增加订单容量
    if self.level <= 30 then
        self.max_order_count = 2 + math.floor(self.level / 3)
    end

    -- 每2级增加耐心系数
    self.wait_alpha = 1.0 + math.tofixed(self.level) / 15

    self:update_info()
end

---升级
function _store.Store:levelup()
    local cost = self:get_levelup_money()
    if self.assets >= cost and self.level < 100 then
        self:deduct_assets(cost)
        self:set_level(self.level + 1)
        return true
    end
    return false
end

---增加资产
---@param count integer
function _store.Store:improve_assets(count)
    self.assets = self.assets + count
end

---扣除资产
---@param count integer
function _store.Store:deduct_assets(count)
    self.assets = math.max(self.assets - count, 0)
end

return _store
